/*********************************************************************************************************
**
**                                   GJB 标准测试集
**
**                               Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文   件   名: gjb_S0100903GN_2.c
**
** 文件创建日期: 2021 年 1 月 22 日
**
** 描        述: 以限时阻塞方式等待条件变量功能测试
*********************************************************************************************************/
#include <pthread.h>
#include <stdio.h>
#include <math.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <semaphore.h>
#include <sched.h>

// #include "gjb.h"

#define TIMEOUT   5

static int err_count_cv_9032;

pthread_cond_t cond1_cv_9032 = PTHREAD_COND_INITIALIZER;                        /* cond used by the two threads */
pthread_mutex_t mutex1_cv_9032 = PTHREAD_MUTEX_INITIALIZER;                     /* cond used by the two threads */

void * thread1_cv_9032(void *tmp)
{
    int             rc = 0;
    struct timespec timeout;
    struct timespec curtime;

    /*
     * acquire the mutex
     */
    rc  = pthread_mutex_lock(&mutex1_cv_9032);
    if(rc != 0) {
        printf("test failed.pthread_mutex_lock\n");
        err_count_cv_9032++;
        return (void *)-1;
    }

    if (clock_gettime(CLOCK_REALTIME, &curtime) != 0) {
        printf("Fail to get current time\n");
        err_count_cv_9032++;
        return (void *)-1;
    }

    timeout.tv_sec = curtime.tv_sec;

    timeout.tv_nsec = curtime.tv_nsec;

    timeout.tv_sec += TIMEOUT;

    /*
     *  传入无效的参数类型
     */
    rc = pthread_cond_timedwait(&mutex1_cv_9032, &mutex1_cv_9032, &timeout);
    if(rc == EINVAL ) {
        printf("test 1 pass,pthread_cond_timedwait return EINVAL \n");

    } else {
        printf("test 1 failed.pthread_cond_timedwait should return EINVAL  , but return %d\n",rc);
        err_count_cv_9032++;
        return (void *)-1;
    }

    /*
     *  传入无效的参数类型
     */
    rc = pthread_cond_timedwait(&cond1_cv_9032, &cond1_cv_9032 , &timeout);
    if(rc == EINVAL ) {
        printf("test 2 pass,pthread_cond_timedwait return EINVAL \n");

    } else {
        printf("test 2 failed.pthread_cond_timedwait should return EINVAL  , but return %d\n",rc);
        err_count_cv_9032++;
        return (void *)-1;
    }

    rc = pthread_cond_timedwait(NULL, &mutex1_cv_9032, &timeout);
    if(rc == EINVAL ) {
        printf("test 3 pass,pthread_cond_timedwait return EINVAL \n");

    } else {
        printf("test 3 failed.pthread_cond_timedwait should return EINVAL  , but return %d\n",rc);
        err_count_cv_9032++;
        return (void *)-1;
    }

    rc = pthread_cond_timedwait(&cond1_cv_9032, NULL, &timeout);
    if(rc == EINVAL ) {
        printf("test 4 pass,pthread_cond_timedwait return EINVAL \n");

    } else {
        printf("test 4 failed.pthread_cond_timedwait should return EINVAL  , but return %d\n",rc);
        err_count_cv_9032++;
        return (void *)-1;
    }

    rc = pthread_cond_timedwait(&cond1_cv_9032, &mutex1_cv_9032, &timeout);
    if(rc != 0 ) {
        printf("test failed.pthread_cond_timedwait should return 0  , but return %d\n",rc);
        err_count_cv_9032++;
        return (void *)-1;
    }

    rc = pthread_mutex_unlock(&mutex1_cv_9032);
    if(rc != 0) {
        printf("test failed.pthread_mutex_unlock\n");
        err_count_cv_9032++;
        return (void *)-1;
    }
    sleep(2);

    pthread_cond_signal(&cond1_cv_9032);

    return NULL;
}

int gjb_S0100903GN_2(int argc, char **argv)
{
    pthread_t       low_id;
    pthread_mutex_t mutex2;
    struct timespec timeout;

    struct timespec curtime;
    int             rc = 0;

    pthread_mutex_init(&mutex2,NULL);

    /*
     * Create a new thread with default attributes
     */
    rc = pthread_create(&low_id, NULL, thread1_cv_9032, NULL);
    if(rc != 0) {
        printf("pthread_create\n");
        goto __errno_handle;
    }

    /*
     * Let the other thread run
     */
    sleep(3);

    pthread_cond_signal(&cond1_cv_9032);

    if (clock_gettime(CLOCK_REALTIME, &curtime) != 0) {
     printf("Fail to get current time\n");
     goto __errno_handle;
    }

    timeout.tv_sec = curtime.tv_sec;

    timeout.tv_nsec = curtime.tv_nsec;

    timeout.tv_sec += TIMEOUT;

    rc  = pthread_mutex_lock(&mutex2);
    if(rc != 0) {
        printf("test failed.pthread_mutex_lock\n");
        goto __errno_handle;
    }

    rc = pthread_cond_timedwait(&cond1_cv_9032, &mutex2, &timeout);
    if(rc == EINVAL ) {
        printf("test 5 pass,pthread_cond_timedwait return EINVAL \n");

    } else {
        printf("test 5 failed.pthread_cond_timedwait should return EINVAL  , but return %d\n",rc);
        goto __errno_handle;
    }

    rc = pthread_mutex_unlock(&mutex2);
    if(rc != 0) {
        printf("test failed.pthread_mutex_unlock\n");
        goto __errno_handle;
    }

    if (err_count_cv_9032) {
        goto __errno_handle;
    }

    printf("<RSLT>..................................................[(0)]\n \n \n");

    return  (0);   

__errno_handle:

    printf("<RSLT>..................................................[(-1)]\n \n \n");
    return  (-1);
}
